home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / util1 / whence.lha / WHENCE / Whence.c < prev   
C/C++ Source or Header  |  1995-10-31  |  14KB  |  817 lines

  1.  
  2. #define    VERSION    "1.4 "
  3. /**
  4.  ***** Whence
  5.  *
  6.  *****     Searches all directories in AmigaDos PATH for the given
  7.  *    command name, and reports all instances found.
  8.  *
  9.  *    Directories of the same name are ignored.
  10.  *
  11.  *    The first instance printed would be the one AmigaDos executes.
  12.  *
  13.  *    Handles from 1.2 upwards. 2.04 Internals/residents
  14.  *    are reported.
  15.  *
  16.  *    Redundant paths are NOT reported (in contrast with AmigaDos 'which')
  17.  *
  18.  *    Path, File size and date is printed.
  19.  *
  20.  *    Algorithms depend entirely on observed format of
  21.  *    Path and Assign commands executed under AmigaDos 2.04 , i.e
  22.  *    it is assumed that they follow previous releases.
  23.  *
  24.  *
  25.  *
  26.  *
  27.  *****    Written by Gary Duncan
  28.  *
  29.  *    Bug reports etc via e-mail to gduncan@werple.net.au 
  30.  *
  31.  *
  32.  *****    Freely distributable for non-commercial purposes.
  33.  *    Please keep this header intact.
  34.  *
  35.  *
  36.  *    Compiles under SAS 6.2
  37.  *
  38.  *    Formatted with 'indent -gnu' ; a big time-saving program.
  39.  *
  40.  ***** Function List :-
  41.  
  42.     brk
  43.     main
  44.     chk_cdir
  45.     put_path
  46.     get_fib
  47.     get_cwd
  48.     add_C_assign
  49.     search_resident
  50.     dss2str
  51.     usage
  52.     hexit
  53.  
  54.  
  55. Version    Date     Changes
  56. ~~~~~~~ ~~~~    ~~~~~~
  57.  
  58. 1.0     29Oct93 Original release
  59. 1.1    24Jan94 used __AMIGADATE__
  60. 1.2    28Nov94 uses manual __AMIGADATE__ (buggy) 
  61. 1.3    27Apr95 reactivated __AMIGADATE__ , corrected exit state 
  62. 1.4    30Sep95 No code changed ( comments corrected)  
  63.  
  64.  
  65.  
  66.  
  67.  
  68. *************************************************************************/
  69.  
  70. #include <stdlib.h>
  71. #include <stdio.h>
  72. #include <fcntl.h>
  73. #include <dos.h>
  74. #include <ctype.h>
  75. #include <exec/execbase.h>
  76. #include <exec/types.h>
  77. #include <string.h>
  78. #include <time.h>
  79. #include <exec/memory.h>
  80. #include <libraries/dosextens.h>
  81. #include <proto/dos.h>
  82. #include <clib/intuition_protos.h>
  83. #include <clib/utility_protos.h>
  84. #include <proto/exec.h>
  85. #include <devices/serial.h>
  86. #include <devices/timer.h>
  87. #include <exec/io.h>
  88. #include <utility/date.h>
  89.  
  90.  
  91. #include "typedefs.h"
  92. #include "whence_protos.h"
  93.  
  94.  
  95. #define REDUNDANT ((char *) -1)
  96.  
  97. /*
  98.  * string for AmigaDOS Version Command
  99.  */
  100. char A_vers[] = "\0$VER: whence\t" VERSION __AMIGADATE__;
  101.  
  102.  
  103. LIBRARY *UtilityBase = NULL;
  104. LIBRARY *BattClockBase;
  105.  
  106. FILE *fp_P = NULL;
  107. FILE *fp_A = NULL;
  108. FILE *fp_R = NULL;
  109. FILE *fp_CD = NULL;
  110.  
  111. static char file_P[20];
  112. static char file_A[20];
  113. static char file_R[20];
  114. static char file_CD[20];
  115.  
  116. FILEINFOBLOCK *fib = NULL;
  117.  
  118. char *paths[64];        /* assume max of 64 dirs in Path */
  119. int path_cnt = 0;
  120.  
  121. BOOLEAN c_flag = FALSE;
  122. int break_flag;
  123.  
  124. int
  125. brk (void)
  126. {
  127.   break_flag++;
  128.   return 0;
  129. }
  130.  
  131.  
  132. /*************************************************************************/
  133.  
  134. int
  135. main (int argc, char **argv)
  136.  
  137. {
  138.   static char buf[256];
  139.   static char line_buf[256];
  140.   LIBRARY *lp;
  141.   char *fname = argv[1];
  142.   char *str;
  143.   char **PP;
  144.   /*
  145.    * set up ^C processing
  146.    */
  147.   if (onbreak (&brk))
  148.     {
  149.       printf ("onbreak fail\n");
  150.       exit (1);
  151.     }
  152.  
  153.   if (argc != 2)
  154.     {
  155.       fprintf (stderr, "Error: need a command name\n");
  156.       usage ();
  157.       hexit (1);
  158.     }
  159.   if (*argv[1] == '-')
  160.     {
  161.       usage ();
  162.       hexit (1);
  163.     }
  164.   /*
  165.    * get a FIB
  166.    */
  167.   fib = AllocMem ((long) sizeof (*fib), MEMF_CLEAR);
  168.   if (fib == NULL)
  169.     {
  170.       fprintf (stderr, "unable to allocate space for fileinfo block\n");
  171.       hexit (1);
  172.     }
  173.  
  174.   /*
  175.    * if below 2.04 version, we won't look for Residents (or itinerants :)
  176.    */
  177.   if (lp = OpenLibrary ("exec.library", 37L))
  178.     {
  179.       CloseLibrary (lp);
  180.  
  181.       /*
  182.        * build Resident File
  183.        */
  184.       sprintf (file_R, "T:wr_%08d", file_R);
  185.       sprintf (buf, "RESIDENT >%s", file_R);
  186.       Execute (buf, 0L, 0L);
  187.  
  188.       if ((fp_R = fopen (file_R, "r")) == NULL)
  189.     {
  190.       fprintf (stderr, "Can't fopen %s\n", file_R);
  191.       hexit (1);
  192.     }
  193.     }
  194.  
  195.   /*
  196.    * build file containing CD
  197.    */
  198.   sprintf (file_CD, "T:wcd_%08d", file_CD);
  199.   sprintf (buf, "CD >%s", file_CD);
  200.   Execute (buf, 0L, 0L);
  201.  
  202.   /*
  203.    * build file containing PATHS
  204.    */
  205.   sprintf (file_P, "T:wp_%08d", file_P);
  206.   sprintf (buf, "PATH >%s", file_P);
  207.   Execute (buf, 0L, 0L);
  208.  
  209.   /*
  210.    * build file containing ASSIGNS
  211.    */
  212.   sprintf (file_A, "T:wa_%08d", file_A);
  213.   sprintf (buf, "ASSIGN >%s", file_A);
  214.   Execute (buf, 0L, 0L);
  215.  
  216.   /*
  217.    * open the files for further manipulation , later
  218.    */
  219.  
  220.   if ((fp_P = fopen (file_P, "r")) == NULL)
  221.     {
  222.       fprintf (stderr, "Can't fopen %s\n", file_P);
  223.       hexit (1);
  224.     }
  225.   if ((fp_A = fopen (file_A, "r")) == NULL)
  226.     {
  227.       fprintf (stderr, "Can't fopen %s\n", file_A);
  228.       hexit (1);
  229.     }
  230.   if ((fp_CD = fopen (file_CD, "r")) == NULL)
  231.     {
  232.       fprintf (stderr, "Can't fopen %s\n", file_CD);
  233.       hexit (1);
  234.     }
  235.   /*
  236.    ***************************************************************
  237.    */
  238.  
  239.   /*
  240.    * if Resident file open, search and report on it first
  241.    * - that's the rules under 2.04
  242.    */
  243.   if (fp_R)
  244.     search_resident (fname);
  245.  
  246.   /*
  247.    * put Path strings into an *array for convenience
  248.    *
  249.    */
  250.  
  251.   path_cnt = 0;
  252.   while ((str = fgets (line_buf, sizeof (line_buf), fp_P)) != NULL)
  253.     {
  254.       char *p;
  255.  
  256.       /*
  257.        * handle "Current directory"
  258.        */
  259.       if (path_cnt == 0)
  260.     {
  261.       str = get_cwd ();
  262.     }
  263.       p = &str[strlen (str) - 1];
  264.       *p = '\0';        /* remove NL */
  265.  
  266.       /*
  267.        * C: is last. Drop it now, handle later
  268.        */
  269.       if (strcmp (str, "C:") == 0)
  270.     {
  271.       continue;
  272.     }
  273.  
  274.       /*
  275.        * copy it to a malloc'd bit of memory
  276.        */
  277.       put_path (str);
  278.     }
  279.  
  280.   /*
  281.    * now handle case where current dir is in Path list
  282.    */
  283.   chk_cdir ();
  284.  
  285.  
  286.   /*
  287.    * now handle C: (last). If 2.04 may be added dirs (+ xxx)
  288.    */
  289.   add_C_assign ();
  290.  
  291.   /*
  292.    * now scan recreated path list
  293.    */
  294.  
  295.   for (PP = paths; *PP; ++PP)
  296.     {
  297.       char buf[256];
  298.  
  299.       if (*PP == REDUNDANT)
  300.     {
  301.       continue;
  302.     }
  303.  
  304.       strcpy (buf, *PP);
  305.       if (buf[strlen (buf) - 1] != ':')
  306.     {
  307.       strcat (buf, "/");
  308.     }
  309.  
  310.       strcat (buf, fname);
  311.  
  312.       chkabort ();
  313.       if (break_flag)
  314.     {
  315.       fprintf (stderr, "^C\n");
  316.       hexit (1);
  317.     }
  318.       if (get_fib (buf) == NULL)
  319.     {
  320. #if 0
  321.       printf ("Not a File (%s)\n", buf);
  322. #endif
  323.       continue;
  324.     }
  325.  
  326.       /*
  327.        * make sure its a file not dir
  328.        */
  329.       if (fib->fib_DirEntryType < 0)
  330.     {
  331.       /*
  332.        * print pathname , size , date
  333.        */
  334.       printf ("%-25s %7d bytes : %s\n", buf, fib->fib_Size,
  335.           dss2str (&fib->fib_Date));
  336.     }
  337.     }
  338.   hexit (0);
  339. }
  340.  
  341. /***************************************************************************
  342.  
  343.  
  344. Name:          chk_cdir
  345.  
  346. Purpose:    checks paths[] to see if current dir entry (#1)
  347.         is replicated below, if so mark as redundant that entry.
  348.  
  349.  
  350. Entry    :
  351.  
  352.  
  353. Returns  :
  354.  
  355.  
  356.  
  357. ****************************************************************************/
  358.  
  359. void
  360. chk_cdir ()
  361. {
  362.   int j;
  363.  
  364.   for (j = 1; j < path_cnt; ++j)
  365.     {
  366.       if (stricmp (paths[0], paths[j]) == 0)
  367.     {
  368. #if 0
  369.       printf ("%s : REDUNDANT\n", paths[j]);
  370. #endif
  371.       free (paths[j]);
  372.       paths[j] = REDUNDANT;
  373.       return;
  374.     }
  375.     }
  376. }
  377.  
  378. /***************************************************************************
  379.  
  380.  
  381. Name:          put_path
  382.  
  383. Purpose:    copies given string to malloc'd memory and put
  384.         its pointer in next slot in paths[].
  385.  
  386.  
  387. Entry    :
  388.  
  389.  
  390. Returns  :
  391.  
  392.  
  393.  
  394. ****************************************************************************/
  395.  
  396. void
  397. put_path (char *str)
  398. {
  399.   if (path_cnt == sizeof (paths))
  400.     {
  401.       fprintf (stderr, "path buffer (64) full!\n");
  402.       hexit (1);
  403.     }
  404.  
  405.   if ((paths[path_cnt] = malloc (strlen (str) + 1)) == NULL)
  406.     {
  407.       fprintf (stderr, "malloc fail\n");
  408.       hexit (1);
  409.     }
  410.   strcpy (paths[path_cnt++], str);
  411. #if 0
  412.   printf ("put_path : %s\n", paths[path_cnt - 1]);
  413. #endif
  414. }
  415.  
  416. /***************************************************************************
  417.  
  418.  
  419. Name:         get_fib
  420.  
  421. Purpose:    given a file name, return with a FIB ,
  422.         or NULL if non-existent
  423.  
  424.  
  425. Entry    :
  426.  
  427.  
  428. Returns  :
  429.  
  430.  
  431.  
  432. ****************************************************************************/
  433.  
  434.  
  435. FILEINFOBLOCK *
  436. get_fib (char *fname)
  437.  
  438. {
  439.   BPTR flock;
  440.  
  441.  
  442.   if (!(flock = Lock (fname, ACCESS_READ)))
  443.     {
  444.       return NULL;
  445.     }
  446.  
  447.   if (!Examine (flock, fib))
  448.     {
  449.       UnLock (flock);
  450.       return NULL;
  451.     }
  452.  
  453.   UnLock (flock);
  454.   return fib;
  455. }
  456.  
  457. /***************************************************************************
  458.  
  459.  
  460.   Function :    get_cwd
  461.  
  462.   Purpose:      returns with path to current dir
  463.  
  464.   Entry    :
  465.  
  466.   Returns  :
  467.  
  468.  
  469. ****************************************************************************/
  470.  
  471.  
  472. char *
  473. get_cwd ()
  474. {
  475.   static char buf[128];
  476.  
  477.  
  478.   if (fgets (buf, sizeof (buf), fp_CD) == NULL)
  479.     {
  480.       fprintf (stderr, "fatal error reading cwd\n");
  481.       hexit (1);
  482.     }
  483.   return buf;
  484.  
  485. }
  486.  
  487. /***************************************************************************
  488.  
  489.  
  490.   Function :    add_C_assign
  491.  
  492.   Purpose:         scans Assign file and adds C: info to path[]
  493.  
  494.   Entry    :
  495.  
  496.   Returns  :
  497.  
  498.  
  499. ****************************************************************************/
  500.  
  501.  
  502. void
  503. add_C_assign ()
  504. {
  505.   static char buf[128];
  506.   BOOLEAN flag = FALSE;
  507.   char *p;
  508.   int p_c;
  509.   int j;
  510.  
  511.   if (fseek (fp_A, 0L, SEEK_SET) == -1)
  512.     {
  513.       fprintf (stderr, "\nget_assign seek error\n");
  514.       hexit (1);
  515.     }
  516.   while (1)
  517.     {
  518.       if (fgets (buf, sizeof (buf), fp_A) == NULL)
  519.     {
  520.       return;
  521.     }
  522.       buf[strlen (buf) - 1] = '\0';    /* zap NL */
  523.       /*
  524.        * point to start of last field (dir)
  525.        */
  526.  
  527.       p = &buf[strlen (buf) - 1];
  528.       while (*(p - 1) != ' ')
  529.     --p;
  530.  
  531.       /*
  532.        * when c is found , put its dirs into paths[]
  533.        */
  534.       if (strnicmp (buf, "c ", 2) == 0)
  535.     {
  536.       flag = TRUE;
  537.       p_c = path_cnt;    /* hold index */
  538.       put_path (p);
  539.     }
  540.       else if (flag)
  541.     {
  542.       if (*(p - 2) == '+')
  543.         {
  544.           put_path (p);
  545.         }
  546.       else
  547.         /* end */
  548.         {
  549.           /*
  550.            * now scan paths[] to see if c: was already there (above in
  551.            * array). If so mark as redundant c: dir
  552.            */
  553.           for (j = 0; j < p_c; ++j)
  554.         {
  555.           if (strcmp (paths[j], paths[p_c]) == 0)
  556.             {
  557.               /*
  558.                * found a matching dir, mark it as a null
  559.                */
  560.               free (paths[p_c]);
  561.               paths[p_c] = REDUNDANT;
  562.               return;
  563.  
  564.             }
  565.         }
  566.         }
  567.     }
  568.     }
  569. }
  570.  
  571. /***************************************************************************
  572.  
  573.  
  574.   Function :    search_resident
  575.  
  576.   Purpose:      searches for resident commands
  577.  
  578.   Entry    :
  579.  
  580.   Returns  :
  581.  
  582.  
  583. ****************************************************************************/
  584.  
  585. void
  586. search_resident (char *name)
  587. {
  588.   char buf[80];
  589.  
  590.   /*
  591.    * skip first line
  592.    */
  593.   if (fgets (buf, sizeof (buf), fp_R) == NULL)
  594.     {
  595.       return;
  596.     }
  597.   /*
  598.    * skip second line
  599.    */
  600.   if (fgets (buf, sizeof (buf), fp_R) == NULL)
  601.     {
  602.       return;
  603.     }
  604.  
  605.   while (1)
  606.     {
  607.       char *p = buf;
  608.  
  609.       if (fgets (buf, sizeof (buf), fp_R) == NULL)
  610.     {
  611.       return;
  612.     }
  613.  
  614.       while (*++p != ' ');
  615.  
  616.       *p = '\0';
  617.       if (strlen (name) == strlen (buf))
  618.     {
  619.       if (stricmp (name, buf) == 0)
  620.         {
  621.           while (*++p == ' ');
  622.  
  623.           if (isdigit (*p))
  624.         printf ("RES %s\n", name);
  625.           else
  626.         printf ("INTERNAL %s\n", name);
  627.  
  628.           return;
  629.         }
  630.     }
  631.     }
  632. }
  633.  
  634. /***************************************************************************
  635.  
  636.  
  637.   Function :      dss2str
  638.  
  639.   Purpose:    generates a date string
  640.  
  641.   Entry    :    Datestamp
  642.  
  643.  
  644.   Returns  :    ptr to date string
  645.  
  646.  
  647.  
  648. ****************************************************************************/
  649.  
  650.  
  651. char *
  652. dss2str (DATESTAMP * ds)
  653.  
  654. {
  655.   static DM days_month[] =
  656.   {
  657.     31, "Jan",
  658.     28, "Feb",
  659.     31, "Mar",
  660.     30, "Apr",
  661.     31, "May",
  662.     30, "Jun",
  663.     31, "Jul",
  664.     31, "Aug",
  665.     30, "Sep",
  666.     31, "Oct",
  667.     30, "Nov",
  668.     31, "Dec",
  669.   };
  670.   static char buf[40];
  671.   struct tm Time;
  672.  
  673.   int j;
  674.   long time, ago;
  675.  
  676.   /*
  677.    * convert to a secs
  678.    */
  679.   time = ds->ds_Days * (24 * 60 * 60);
  680.   time += ds->ds_Minute * 60;
  681.   time += ds->ds_Tick / TICKS_PER_SECOND;
  682.  
  683.   Time.tm_sec = time % 60;
  684.   time /= 60;
  685.   Time.tm_min = time % 60;
  686.   time /= 60;
  687.   Time.tm_hour = time % 24;
  688.   time /= 24;
  689.   Time.tm_wday = time % 7;
  690.   Time.tm_year = 78 + (time / (4 * 365 + 1)) * 4;
  691.   time %= 4 * 365 + 1;
  692.  
  693.  
  694.   while (time)
  695.     {
  696.       ago = 365;
  697.       if ((Time.tm_year & 3) == 0)    /* leap year */
  698.     ago++;
  699.       if (time < ago)
  700.     break;
  701.       time -= ago;
  702.       Time.tm_year++;
  703.     }
  704.   Time.tm_yday = ++time;
  705.  
  706.   for (j = 0; j < 12; j++)
  707.     {
  708.       ago = days_month[j].days;
  709.       if (j == 1 && (Time.tm_year & 3) == 0)    /* Feb , and leap year ? */
  710.     ago++;
  711.       if (time <= ago)
  712.     break;
  713.       time -= ago;
  714.     }
  715.   Time.tm_mon = j;
  716.   Time.tm_mday = time;
  717.  
  718.   /* date format : 23-dec-88 22:33:01  */
  719.  
  720.   sprintf (buf, "%02d-%s-%2d %02d:%02d:%02d",
  721.        Time.tm_mday,
  722.        days_month[Time.tm_mon].months,
  723.        Time.tm_year,
  724.        Time.tm_hour,
  725.        Time.tm_min,
  726.        Time.tm_sec
  727.     );
  728.  
  729.   return (buf);
  730. }
  731.  
  732. /***************************************************************************
  733.  
  734.  
  735.   Function :    usage
  736.  
  737.   Purpose:      prints usage
  738.  
  739.   Entry    :
  740.  
  741.   Returns  :
  742.  
  743.  
  744. ****************************************************************************/
  745.  
  746. void
  747. usage ()
  748. {
  749.   static char *rats[] =
  750.   {
  751.     "usage: whence <command>",
  752.     ""                /* empty string ;TERM */
  753.   };
  754.   int j = 0;
  755.   char *ptr;
  756.  
  757.  
  758.  
  759.   fprintf (stderr,
  760. /****/ "Whence: prints paths to given command in AmigaDos search path\n\n\
  761. Version %s [%s] written by gduncan@philips.oz.au\n", VERSION, __DATE__);
  762.  
  763.   while (*(ptr = rats[j++]))
  764.     fprintf (stderr, "%s\n", ptr);
  765. }
  766.  
  767. /***************************************************************************
  768.  
  769.  
  770.   Function :    hexit
  771.  
  772.   Purpose:      cleans up and exits
  773.  
  774.   Entry    :
  775.  
  776.   Returns  :
  777.  
  778.  
  779. ****************************************************************************/
  780.  
  781. void
  782. hexit (int k)
  783. {
  784.   int j;
  785.  
  786.   fclose (fp_R);
  787.   unlink (file_R);
  788.  
  789.   fclose (fp_CD);
  790.   unlink (file_CD);
  791.  
  792.   fclose (fp_P);
  793.   unlink (file_P);
  794.  
  795.   fclose (fp_A);
  796.   unlink (file_A);
  797.   if (fib)
  798.     FreeMem (fib, (long) sizeof (*fib));
  799.  
  800.   /*
  801.    * release path array memory
  802.    */
  803.   for (j = 0; j < path_cnt; ++j)
  804.     {
  805.       char *p = paths[j];
  806.  
  807.       if (p && (p != REDUNDANT))
  808.     free (p);
  809.  
  810.     }
  811.  
  812.   exit (k);
  813. }
  814.  
  815. /*--*/
  816. €
  817.